-----------
--GLOBALS--
-----------
if not IWR then IWR = {} end

function IWR.Now()
	return Inspect.Time.Frame()
end

IWR.player		= 'player'
IWR.mouseover	= 'mouseover'
IWR.target		= 'player.target'
IWR.focus		= 'focus'
IWR.playerpet	= 'player.pet'

IWR.GCD				= 1.5
IWR.lastindex		= nil
IWR.ismoving		= false
IWR.enabled			= false
IWR.lastexecute		= IWR.Now()
IWR.spamspeed		= 0.05
IWR.rotationloaded	= false
IWR.playerid		= Inspect.Unit.Lookup(IWR.player)
IWR.lastx			= nil
IWR.lasty			= nil
IWR.lastz			= nil
IWR.loaded			= false
IWR.Debug			= false
IWR.lastbuffupdate	= IWR.Now()
IWR.buffupdatespeed	= 1

IWR.keyframe = nil
IWR.toggleframe = nil

if not IWR.UnitDetails then
	IWR.UnitDetails = {
		[IWR.player]	= {},
		[IWR.playerpet]	= {},
		[IWR.mouseover]	= {},
		[IWR.target]	= {},
		[IWR.focus]		= {}
	}
end

if not IWR.UnitBuffs then
	IWR.UnitBuffs = {
		[IWR.player]	= {},
		[IWR.playerpet]	= {},
		[IWR.mouseover]	= {},
		[IWR.target]	= {},
		[IWR.focus]		= {}
	}
end

if not IWR.Abilities then IWR.Abilities = {} end

if not IWR.AbilitiesCD then IWR.AbilitiesCD = {} end

if not IWR.Castbar then
	IWR.Castbar = {
		[IWR.player]	= {},
		[IWR.playerpet]	= {},
		[IWR.mouseover]	= {},
		[IWR.target]	= {},
		[IWR.focus]		= {}
	}
end

if not IWR.Rotation then IWR.Rotation = {} end
------------
--/GLOBALS--
------------

------------
--ROTATION--
------------
function IWR.RotationFunc()
	for i=1, #IWR.Rotation do
		local check = IWR.RotationIteration(i)
		if check then
			IWR.lastindex = i
			local rotationline = IWR.Rotation[i]
			if rotationline.setVCD_line and rotationline.setVCD_VCD then
				for j=1, #rotationline.setVCD_line do
					IWR.Rotation[rotationline.setVCD_line[j]].lineavailabletime = IWR.Now() + rotationline.setVCD_VCD[j]
				end
			end
			return IWR.Rotation[i].key
		end
	end
	return false
end

function IWR.RotationIteration(index)
	local ability = IWR.Rotation[index].id
	local conditions = IWR.Rotation[index]
	if ability then
		if IWR.UnitDetails[conditions.unit] and IWR.UnitDetails[conditions.unit].id then
			if conditions.instant_buff then
				local flag = false
				for buffid, buffdetails in pairs(IWR.UnitBuffs[IWR.player]) do
					if buffdetails.name == conditions.instant_buff then
						flag = true
						break
					end
				end
				conditions.instant = flag
			end
			if conditions.agressivecdcheck and conditions.GCDrefline then
				local abilitydetail = Inspect.Ability.New.Detail(ability)
				local GCDabilitydetail = Inspect.Ability.New.Detail(IWR.Rotation[conditions.GCDrefline].id)
				if abilitydetail.currentCooldownRemaining then
					if GCDabilitydetail.currentCooldownRemaining and abilitydetail.currentCooldownRemaining > GCDabilitydetail.currentCooldownRemaining + 0.05 then
						IWR.AbilitiesCD[ability].availabletime = IWR.Now() + abilitydetail.currentCooldownRemaining
					else
						IWR.AbilitiesCD[ability].availabletime = IWR.Now()
					end
				else
					IWR.AbilitiesCD[ability].availabletime = IWR.Now()
				end
			end
			if IWR.Now() >= IWR.AbilitiesCD[ability].availabletime and IWR.Now() >= IWR.Rotation[index].lineavailabletime then
				if (not IWR.ismoving or (conditions.castonmove or conditions.instant)) and not IWR.Abilities[ability].outOfRange and not IWR.Abilities[ability].unusable and (not IWR.Castbar[IWR.player].channeled or conditions.whilechannel) then
					local playerhealth = nil
					if IWR.UnitDetails[IWR.player].health and IWR.UnitDetails[IWR.player].healthMax then
						playerhealth = IWR.UnitDetails[IWR.player].health/IWR.UnitDetails[IWR.player].healthMax*100
					end
					local unithealth = nil
					if IWR.UnitDetails[conditions.unit].health and IWR.UnitDetails[conditions.unit].healthMax then
						unithealth = IWR.UnitDetails[conditions.unit].health/IWR.UnitDetails[conditions.unit].healthMax*100
					end
					local playermana = nil
					if IWR.UnitDetails[IWR.player].mana and IWR.UnitDetails[IWR.player].manaMax then
						playermana = IWR.UnitDetails[IWR.player].mana/IWR.UnitDetails[IWR.player].manaMax*100
					end
					
					-- Unit in combat
					if conditions.incombat then
						if not IWR.UnitDetails[conditions.unit].combat and not IWR.UnitDetails[IWR.player].combat then
							return false
						end
					end
				
					-- Charge more then
					if conditions.charge_more then
						if IWR.UnitDetails[IWR.player].charge < conditions.charge_more then
							return false
						end
					end
				
					--Charge less then
					if conditions.charge_less then
						if IWR.UnitDetails[IWR.player].charge >= conditions.charge_less then
							return false
						end
					end
				
					--Combo more then
					if conditions.combo_more then
						if IWR.UnitDetails[IWR.player].combo < conditions.combo_more then
							return false
						end
					end
				
					--Combo less then
					if conditions.combo_less then
						if IWR.UnitDetails[IWR.player].combo >= conditions.combo_less then
							return false
						end
					end
				
					--Energy more then
					if conditions.energy_more then
						if IWR.UnitDetails[IWR.player].energy < conditions.energy_more then
							return false
						end
					end
				
					--Energy less then
					if conditions.energy_less then
						if IWR.UnitDetails[IWR.player].energy >= conditions.energy_less then
							return false
						end
					end
				
					--Player health more then
					if conditions.playerhealth_more then
						if not playerhealth then
							return false
						elseif playerhealth < conditions.playerhealth_more then
							return false
						end
					end
				
					--Player health less then
					if conditions.playerhealth_less then
						if not playerhealth then
							return false
						elseif playerhealth >= conditions.playerhealth_less or playerhealth == 0 then
							return false
						end
					end
				
					--Unit health more then
					if conditions.unithealth_more then
						if not unithealth then
							return false
						elseif unithealth < conditions.unithealth_more then
							return false
						end
					end
				
					--Unit health less then
					if conditions.unithealth_less then
						if not unithealth then
							return false
						elseif unithealth >= conditions.unithealth_less or unithealth == 0 then
							return false
						end
					end
				
					--Player mana more then
					if conditions.playermana_more then
						if not playermana then
							return false
						elseif playermana < conditions.playermana_more then
							return false
						end
					end
				
					--Player mana less then
					if conditions.playermana_less then
						if not playermana then
							return false
						elseif playermana >= conditions.playermana_less then
							return false
						end
					end
				
					--Player has buff
					if conditions.playerbuff_true then
						local flag = false
						for i, buff in pairs(conditions.playerbuff_true) do
							local iflag = false
							for buffid, buffdetails in pairs(IWR.UnitBuffs[IWR.player]) do
								if buffdetails.name == buff then
									iflag = true
									break
								end
							end
							if iflag then
								flag = true
							else
								flag = false
								break
							end
						end
						if not flag then
							return false
						end
					end
				
					--Player doesn't has buff
					if conditions.playerbuff_false then
						local flag = false
						for i, buff in pairs(conditions.playerbuff_false) do
							local iflag = false
							for buffid, buffdetails in pairs(IWR.UnitBuffs[IWR.player]) do
								if buffdetails.name == buff then
									iflag = true
									break
								end
							end
							if iflag then
								flag = true
								break
							else
								flag = false
							end
						end
						if flag then
							return false
						end
					end
				
					--Player buff stacks more then
					if conditions.playerbuff_stack_more then
						local stacks = 1
						for buffid, buffdetails in pairs(IWR.UnitBuffs[IWR.player]) do
							if buffdetails.name == conditions.playerbuff_true[1] then
								if buffdetails.stack then
									stacks = buffdetails.stack
								end
								break
							end
						end
						if stacks < conditions.playerbuff_stack_more then
							return false
						end
					end
				
					--Player buff stacks less then
					if conditions.playerbuff_stack_less then
						local stacks = 1
						for buffid, buffdetails in pairs(IWR.UnitBuffs[IWR.player]) do
							if buffdetails.name == conditions.playerbuff_true[1] then
								if buffdetails.stack then
									stacks = buffdetails.stack
								end
								break
							end
						end
						if stacks >= conditions.playerbuff_stack_less then
							return false
						end
					end
				
					--Player buff remain more then
					if conditions.playerbuff_remain_more then
						local remain = 0
						for buffid, buffdetails in pairs(IWR.UnitBuffs[IWR.player]) do
							if buffdetails.name == conditions.playerbuff_true[1] then
								if buffdetails.remaining then
									remain = buffdetails.remaining
								end
								break
							end
						end
						if remain < conditions.playerbuff_remain_more then
							return false
						end
					end
				
					--Player buff remain less then
					if conditions.playerbuff_remain_less then
						local remain = 0
						for buffid, buffdetails in pairs(IWR.UnitBuffs[IWR.player]) do
							if buffdetails.name == conditions.playerbuff_true[1] then
								if buffdetails.remaining then
									remain = buffdetails.remaining
								end
								break
							end
						end
						if remain >= conditions.playerbuff_remain_less then
							return false
						end
					end
				
					--Use on unit with name
					if conditions.unitname_useon then
						local flag = false
						for i, unitname in pairs(conditions.unitname_useon) do
							if unitname == IWR.UnitDetails[conditions.unit].name then
								flag = true
								break
							end
						end
						if not flag then
							return false
						end
					end
				
					--Don't use on unit with name
					if conditions.unitname_ignore then
						local flag = false
						for i, unitname in pairs(conditions.unitname_ignore) do
							if unitname == IWR.UnitDetails[conditions.unit].name then
								flag = true
								break
							end
						end
						if flag then
							return false
						end
					end
				
					--Unit has buff
					if conditions.unitbuff_true then
						local flag = false
						for buffid, buffdetails in pairs(IWR.UnitBuffs[conditions.unit]) do
							if buffdetails.name == conditions.unitbuff_true then
								if conditions.unitbuff_caster then
									if buffdetails.caster == conditions.unitbuff_caster then
										flag = true
										break
									end
								else
									flag = true
									break
								end
							end
						end
						if not flag then
							return false
						end
					end
				
					--Unit doesn't has buff
					if conditions.unitbuff_false then
						local flag = false
						for buffid, buffdetails in pairs(IWR.UnitBuffs[conditions.unit]) do
							if buffdetails.name == conditions.unitbuff_false then
								if conditions.unitbuff_caster then
									if buffdetails.caster == conditions.unitbuff_caster then
										flag = true
										break
									end
								else
									flag = true
									break
								end
							end
						end
						if flag then
							return false
						end
					end
				
					--Unit buff stacks more then
					if conditions.unitbuff_stack_more then
						local stacks = 1
						for buffid, buffdetails in pairs(IWR.UnitBuffs[conditions.unit]) do
							if buffdetails.name == conditions.unitbuff_true then
								if conditions.unitbuff_caster then
									if buffdetails.caster == conditions.unitbuff_caster then
										if buffdetails.stack then
											stacks = buffdetails.stack
										end
										break
									end
								else
									if buffdetails.stack then
										stacks = buffdetails.stack
									end
									break
								end
							end
						end
						if stacks < conditions.unitbuff_stack_more then
							return false
						end
					end
				
					--Unit buff stacks less then
					if conditions.unitbuff_stack_less then
						local stacks = 1
						for buffid, buffdetails in pairs(IWR.UnitBuffs[conditions.unit]) do
							if buffdetails.name == conditions.unitbuff_true then
								if conditions.unitbuff_caster then
									if buffdetails.caster == conditions.unitbuff_caster then
										if buffdetails.stack then
											stacks = buffdetails.stack
										end
										break
									end
								else
									if buffdetails.stack then
										stacks = buffdetails.stack
									end
									break
								end
							end
						end
						if stacks >= conditions.unitbuff_stack_less then
							return false
						end
					end
				
					--Unit buff remain more then
					if conditions.unitbuff_remain_more then
						local remain = 0
						for buffid, buffdetails in pairs(IWR.UnitBuffs[conditions.unit]) do
							if buffdetails.name == conditions.unitbuff_true then
								if conditions.unitbuff_caster then
									if buffdetails.caster == conditions.unitbuff_caster then
										if buffdetails.remaining then
											remain = buffdetails.remaining
										end
										break
									end
								else
									if buffdetails.remaining then
										remain = buffdetails.remaining
									end
									break
								end
							end
						end
						if remain < conditions.unitbuff_remain_more then
							return false
						end
					end
				
					--Unit buff remain less then
					if conditions.unitbuff_remain_less then
						local remain = 0
						for buffid, buffdetails in pairs(IWR.UnitBuffs[conditions.unit]) do
							if buffdetails.name == conditions.unitbuff_true then
								if conditions.unitbuff_caster then
									if buffdetails.caster == conditions.unitbuff_caster then
										if buffdetails.remaining then
											remain = buffdetails.remaining
										end
										break
									end
								else
									if buffdetails.remaining then
										remain = buffdetails.remaining
									end
									break
								end
							end
						end
						if remain >= conditions.unitbuff_remain_less then
							return false
						end
					end
				
					--Cast when specified ability is on CD
					if conditions.abilityoncd then
						for abilityid,details in pairs(IWR.Abilities) do
							if details.name == conditions.abilityoncd then
								if conditions.abilityoncdless and IWR.AbilitiesCD[details.id].availabletime - IWR.Now() > conditions.abilityoncdless then
									return false
								elseif conditions.abilityoncdmore and IWR.AbilitiesCD[details.id].availabletime - IWR.Now() < conditions.abilityoncdmore then
									return false
								elseif IWR.AbilitiesCD[details.id].availabletime < (IWR.Now() + (IWR.GCD/2)) then
									return false
								end
							end
						end
					end
				
					--Cast when specified ability is ready
					if conditions.abilityready then
						for abilityid,details in pairs(IWR.Abilities) do
							if details.name == conditions.abilityready then
								if IWR.AbilitiesCD[details.id].availabletime > (IWR.Now() + (IWR.GCD/2)) then
									return false
								end
							end
						end
					end
				
					--Cast only if unit relation match
					if conditions.relation then
						if IWR.UnitDetails[conditions.unit].relation then
							if (IWR.UnitDetails[conditions.unit].relation ~= conditions.relation) then
								return false
							end
						else
							if conditions.relation == 'friendly' then
								return false
							end
						end
					end
				
					--Cast only if unit is casting specified spell
					if conditions.unitcasting then
						if conditions.unit ~= IWR.player then
							IWR.Castbar[conditions.unit] = Inspect.Unit.Castbar(conditions.unit)
						end
						if IWR.Castbar[conditions.unit] and IWR.Castbar[conditions.unit].abilityName then
							local flag = false
							for i, ability in pairs(conditions.unitcasting) do
								if IWR.Castbar[conditions.unit].abilityName == ability then
									flag = true
									break
								end
							end
							if not flag then
								return false
							end
						else
							return false
						end
					end
				else
					return false
				end
			else
				return false
			end
		else
			return false
		end
		return true
	else
	 return false
	end
end

function IWR.Rotation_MapIDs()
	if IWR.Debug then
		Command.Console.Display('general', true, '<font color="#FFCC00">***Initializing ROTATION</font>', true)
	end
	local noerror = true
	for i, details in pairs(IWR.Rotation) do
		if details then
			local flag = false
			if not details.id then
				for abilityid, abilitydetails in pairs(IWR.Abilities) do
					if abilitydetails.name == details.name then
						details.id = abilityid
						flag = true
						if IWR.Debug then
							Command.Console.Display('general', true, '<font color="#00FF00">Ability ' .. details.name .. ' initialized with piority ' .. i ..'</font>', true)
						end
					end
				end
			else
				flag = true
				if IWR.Debug then
					Command.Console.Display('general', true, '<font color="#00FF00">SPECIFIC ability ' .. details.name .. ' initialized with piority ' .. i ..'</font>', true)
				end
			end
			if not flag then
				noerror = false
				if IWR.Debug then
					Command.Console.Display('general', true, '<font color="#FF0000">Ability ' .. details.name .. ' is not learned or temporary! Rotation may break,use with caution!</font>', true)
				end
			end
			details.lineavailabletime = IWR.Now()
		end
	end
	if noerror then
		IWR.rotationloaded = true
		if IWR.Debug then
			Command.Console.Display('general', true, '<font color="#00FF00">DONE</font>', true)
		end
	else
		IWR.rotationloaded = true
		if IWR.Debug then
			Command.Console.Display('general', true, '<font color="#FF0000">WARNING!ROTATION HAVE UNKNOWN OR TEMPORARY ABILITIES!USE IT ONLY IF YOU KNOW WHAT YOU ARE DOING!</font>', true)
		end
	end
end
-------------
--/ROTATION--
-------------
function IWR.OnUpdate()
	if IWR.UnitDetails[IWR.player] then
		if IWR.lastx and IWR.lasty and IWR.lastz then
			if (IWR.lastx == IWR.UnitDetails[IWR.player].coordX) and (IWR.lasty == IWR.UnitDetails[IWR.player].coordY) and (IWR.lastz == IWR.UnitDetails[IWR.player].coordZ) then
				IWR.ismoving = false
			else
				IWR.lastx = IWR.UnitDetails[IWR.player].coordX
				IWR.lasty = IWR.UnitDetails[IWR.player].coordY
				IWR.lastz = IWR.UnitDetails[IWR.player].coordZ
				IWR.ismoving = true
			end
		end
	end
	if IWR.Now() > IWR.lastbuffupdate + IWR.buffupdatespeed then
		IWR.lastbuffupdate = IWR.Now()
		for unit, buffdata in pairs(IWR.UnitBuffs) do
			for buffid, buffdetails in pairs(buffdata) do
				IWR.UnitBuffs[unit][buffid] = Inspect.Buff.Detail(unit, buffid)
			end
		end
	end
	if IWR.loaded then
		if IWR.enabled and IWR.rotationloaded then
			if IWR.Now() > IWR.lastexecute + IWR.spamspeed then
				IWR.toggleframe:SetBackgroundColor(0, 1, 0, 1)
				IWR.lastexecute = IWR.Now()
				local key = IWR.RotationFunc()
				if key then
					IWR.SendHotkey(key)
				else
					IWR.keyframe:SetBackgroundColor(0.5, 0.5, 0.5, 1)
				end
			end
		else
			IWR.keyframe:SetBackgroundColor(0.5, 0.5, 0.5, 1)
			IWR.toggleframe:SetBackgroundColor(0.5, 0.5, 0.5, 1)
		end
	end
end

function IWR.Init()
	if IWR.Debug then
		Command.Console.Display('general', true, '<font color="#FFCC00">***Collecting DETAILS of UNITS</font>', true)
	end
	for unit, unitdetails in pairs(IWR.UnitDetails) do
		IWR.UnitDetails[unit] = Inspect.Unit.Detail(unit)
	end
	IWR.UnitDetails[IWR.player].id = IWR.playerid
	IWR.lastx = IWR.UnitDetails[IWR.player].coordX
	IWR.lasty = IWR.UnitDetails[IWR.player].coordY
	IWR.lastz = IWR.UnitDetails[IWR.player].coordZ
	if IWR.Debug then
		Command.Console.Display('general', true, '<font color="#00FF00">DONE</font>', true)
		Command.Console.Display('general', true, '<font color="#FFCC00">***Collecting BUFFS on UNITS</font>', true)
	end
	for unit, buffdetails in pairs(IWR.UnitBuffs) do
		local tempbufflist = Inspect.Buff.List(unit)
		if tempbufflist then
			IWR.UnitBuffs[unit] = Inspect.Buff.Detail(unit, tempbufflist)
		end
	end
	if IWR.Debug then
		Command.Console.Display('general', true, '<font color="#00FF00">DONE</font>', true)
		Command.Console.Display('general', true, '<font color="#FFCC00">***Collecting ABILITIES info</font>', true)
	end
	local tempabilitylist = Inspect.Ability.New.List()
	if tempabilitylist then
		IWR.Abilities = Inspect.Ability.New.Detail(tempabilitylist)
	end
	for abilityid, abilitydetails in pairs(IWR.Abilities) do
		if abilitydetails then
			IWR.AbilitiesCD[abilityid] = {}
			if abilitydetails.currentCooldownRemaining and abilitydetails.currentCooldownRemaining > 0 then
				IWR.AbilitiesCD[abilityid].availabletime = IWR.Now() + abilitydetails.currentCooldownRemaining
			else
				IWR.AbilitiesCD[abilityid].availabletime = IWR.Now()
			end
		end
	end
	if IWR.Debug then
		Command.Console.Display('general', true, '<font color="#00FF00">DONE</font>', true)
		Command.Console.Display('general', true, '<font color="#FFCC00">***Initializing FRAMES</font>', true)
	end
	local context = UI.CreateContext("Context")
	context:SetStrata("modal")
	IWR.keyframe = UI.CreateFrame("Frame", "IWillRotateKeyFrame", context)
	IWR.keyframe:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 0, 0)
	IWR.keyframe:SetHeight(10)
	IWR.keyframe:SetWidth(10) 
	IWR.keyframe:SetLayer(9999)
	IWR.keyframe:SetBackgroundColor(0.5, 0.5, 0.5, 1)
	IWR.toggleframe = UI.CreateFrame("Frame", "IWillRotateToggleFrame", context)
	IWR.toggleframe:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 10, 0)
	IWR.toggleframe:SetHeight(10)
	IWR.toggleframe:SetWidth(10) 
	IWR.toggleframe:SetLayer(9999)
	IWR.toggleframe:SetBackgroundColor(0.5, 0.5, 0.5, 1)
	if IWR.Debug then
		Command.Console.Display('general', true, '<font color="#00FF00">DONE</font>', true)
	end
	IWR.loaded = true
end

function IWR.SendHotkey(hotkey)
	IWR.keyframe:SetBackgroundColor(hotkey/255, 0, 0, 1) 
end

function IWR.UnitDetailHandler_Charge(chargedata)
	for unitid, chargepoints in pairs(chargedata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.charge = chargepoints
			end
		end
	end
end

function IWR.UnitDetailHandler_Combat(combatdata)
	for unitid, combatstatus in pairs(combatdata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.combat = combatstatus
			end
		end
	end
end

function IWR.UnitDetailHandler_Combo(combodata)
	for unitid, combopoints in pairs(combodata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.combo = combopoints
			end
		end
	end
end

function IWR.UnitDetailHandler_Coord(xcoorddata,ycoorddata,zcoorddata)
	for unitid, xcoord in pairs(xcoorddata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.coordX = xcoord
			end
		end
	end
	for unitid, ycoord in pairs(ycoorddata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.coordY = ycoord
			end
		end
	end
	for unitid, zcoord in pairs(zcoorddata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.coordZ = zcoord
			end
		end
	end
end

function IWR.UnitDetailHandler_Energy(energydata)
	for unitid, energypoints in pairs(energydata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.energy = energypoints
			end
		end
	end
end

function IWR.UnitDetailHandler_Health(healthdata)
	for unitid, healthpoints in pairs(healthdata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.health = healthpoints
			end
		end
	end
end

function IWR.UnitDetailHandler_Mana(manadata)
	for unitid, manapoints in pairs(manadata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.mana = manapoints
			end
		end
	end
end

function IWR.UnitDetailHandler_Radius(radiusdata)
	for unitid, radiuspoints in pairs(radiusdata) do
		for unit, details in pairs(IWR.UnitDetails) do
			if details.id == unitid then
				details.radius = radiuspoints
			end
		end
	end
end

function IWR.BuffHandler_Add(unitid, buffdata)
	for buffid, bufftypeid in pairs(buffdata) do
		for unit, unitdetails in pairs(IWR.UnitDetails) do
			if unitdetails.id == unitid then
				if IWR.UnitBuffs[unit] then
					IWR.UnitBuffs[unit][buffid] = Inspect.Buff.Detail(unit, buffid)
				end
			end
		end
	end
end

function IWR.BuffHandler_Remove(unitid, buffdata)
	for buffid, bufftypeid in pairs(buffdata) do
		for unit, unitdetails in pairs(IWR.UnitDetails) do
			if unitdetails.id == unitid then
				if IWR.UnitBuffs[unit] then
					IWR.UnitBuffs[unit][buffid] = nil
				end
			end
		end
	end
end

function IWR.BuffHandler_Change(unitid, buffdata)
	for buffid, bufftypeid in pairs(buffdata) do
		for unit, unitdetails in pairs(IWR.UnitDetails) do
			if unitdetails.id == unitid then
				if IWR.UnitBuffs[unit] then
					IWR.UnitBuffs[unit][buffid] = Inspect.Buff.Detail(unit, buffid)
				end
			end
		end
	end
end

function IWR.AbilityHandler_Add(abilitydata)
	for abilityid, flag in pairs(abilitydata) do
		if flag then
			IWR.Abilities[abilityid] = Inspect.Ability.New.Detail(abilityid)
			IWR.AbilitiesCD[abilityid] = {}
			if IWR.Abilities[abilityid] then
				for i, details in pairs(IWR.Rotation) do
					if IWR.Abilities[abilityid].name == details.name then
					details.id = abilityid
					end
				end
				if IWR.Abilities[abilityid].currentCooldownRemaining and IWR.Abilities[abilityid].currentCooldownRemaining > 0 then
					IWR.AbilitiesCD[abilityid].availabletime = IWR.Now() + IWR.Abilities[abilityid].currentCooldownRemaining
				else
					IWR.AbilitiesCD[abilityid].availabletime = IWR.Now()
				end
			end
		end
	end
end

function IWR.AbilityHandler_Remove(abilitydata)
	for abilityid, flag in pairs(abilitydata) do
		if IWR.Abilities[abilityid] then
			for i, details in pairs(IWR.Rotation) do
				if IWR.Abilities[abilityid].name == details.name then
					details.id = nil
				end
			end
		end
		IWR.Abilities[abilityid] = nil
		IWR.AbilitiesCD[abilityid] = nil
	end
end

function IWR.AbilityHandler_UsableF(abilitydata)
	for abilityid, flag in pairs(abilitydata) do
		if IWR.Abilities[abilityid] then
			IWR.Abilities[abilityid].unusable = true
		end
	end
end

function IWR.AbilityHandler_UsableT(abilitydata)
	for abilityid, flag in pairs(abilitydata) do
		if IWR.Abilities[abilityid] then
			IWR.Abilities[abilityid].unusable = false
		end
	end
end

function IWR.AbilityHandler_CooldownB(cooldowndata)
	for abilityid, abilitycooldown in pairs(cooldowndata) do
		if IWR.AbilitiesCD[abilityid] then
			if IWR.AbilitiesCD[abilityid].availabletime and IWR.AbilitiesCD[abilityid].availabletime < IWR.Now() then
				if abilitycooldown <= IWR.GCD then
					IWR.AbilitiesCD[abilityid].availabletime = IWR.Now()
					if IWR.lastindex and IWR.Rotation[IWR.lastindex].VCD then
						if IWR.Rotation[IWR.lastindex].lineavailabletime < IWR.Now() then
							IWR.Rotation[IWR.lastindex].lineavailabletime = IWR.Now() + IWR.Rotation[IWR.lastindex].VCD
						end
					end
				else
					IWR.AbilitiesCD[abilityid].availabletime = IWR.Now() + abilitycooldown - 0.3
					if IWR.lastindex and IWR.Rotation[IWR.lastindex].VCD then
						if IWR.Rotation[IWR.lastindex].lineavailabletime < IWR.Now() then
							IWR.Rotation[IWR.lastindex].lineavailabletime = IWR.Now() + abilitycooldown + IWR.Rotation[IWR.lastindex].VCD
						end
					end
				end
			end
		end
	end
	IWR.lastindex = nil
end

function IWR.AbilityHandler_CooldownE(cooldowndata)
	for abilityid, abilitycooldown in pairs(cooldowndata) do
		if IWR.AbilitiesCD[abilityid] then
			IWR.AbilitiesCD[abilityid].availabletime = IWR.Now()
		end
	end
end

function IWR.AbilityHandler_RangeF(abilitydata)
	for abilityid, flag in pairs(abilitydata) do
		if IWR.Abilities[abilityid] then
			IWR.Abilities[abilityid].outOfRange = true
		end
	end
end

function IWR.AbilityHandler_RangeT(abilitydata)
	for abilityid, flag in pairs(abilitydata) do
		if IWR.Abilities[abilityid] then
			IWR.Abilities[abilityid].outOfRange = false
		end
	end
end

function IWR.UnitHandler_Change(unit,unitid)
	if unitid then
		IWR.UnitDetails[unit] = Inspect.Unit.Detail(unit)
		local tempbufflist = Inspect.Buff.List(unit)
		if tempbufflist then
			IWR.UnitBuffs[unit] = Inspect.Buff.Detail(unit, tempbufflist)
		end
	else
		IWR.UnitDetails[unit] = {}
		IWR.UnitBuffs[unit] = {}
	end
end

function IWR.CastbarHandler(unitdata)
	for unitid,flag in pairs(unitdata) do
		if Inspect.Unit.Lookup(unitid) == IWR.player then
			if flag then
				IWR.Castbar[IWR.player] = Inspect.Unit.Castbar(IWR.player)
				if IWR.Castbar[IWR.player].abilityName == 'Changing Role' then
					IWR.rotationloaded = false
					IWR.Rotation = {}
				end
			else
				IWR.Castbar[IWR.player] = {}
			end
		end
		if Inspect.Unit.Lookup(unitid) == IWR.target then
			if flag then
				IWR.Castbar[IWR.target] = Inspect.Unit.Castbar(IWR.target)
			else
				IWR.Castbar[IWR.target] = {}
			end
		end
		if Inspect.Unit.Lookup(unitid) == IWR.focus then
			if flag then
				IWR.Castbar[IWR.focus] = Inspect.Unit.Castbar(IWR.focus)
			else
				IWR.Castbar[IWR.focus] = {}
			end
		end
	end
end

function IWR.UnitAvailabilityFull(h, t)
	for k,v in pairs(t) do
		if v == IWR.player then
			Command.Event.Detach(Event.Unit.Availability.Full, nil, nil, nil, "IWillRotate")
			IWR.Init()
		end
	end
end

function IWR.UnitDetailHandler_Level(unitdata)
	for unitid,value in pairs(unitdata) do
		if unitid == IWR.playerid then
			if IWR.Rotation and IWR.Rotation[1] then
				for i, details in pairs(IWR.Rotation) do
					if details then
						for abilityid, abilitydetails in pairs(IWR.Abilities) do
							if abilitydetails.name == details.name then
								details.id = abilityid
							end
						end
					end
				end
			end
		end
	end
end
----------
--EVENTS--
----------
table.insert(Event.System.Update.Begin					, { IWR.OnUpdate					, "IWillRotate", "Frame update"					})
table.insert(Event.Unit.Detail.Charge					, { IWR.UnitDetailHandler_Charge	, "IWillRotate", "Player charge changed"		})
table.insert(Event.Unit.Detail.Combat					, { IWR.UnitDetailHandler_Combat	, "IWillRotate", "Unit combat status changed"	})
table.insert(Event.Unit.Detail.Combo					, { IWR.UnitDetailHandler_Combo		, "IWillRotate", "Player combo points changed"	})
table.insert(Event.Unit.Detail.Coord					, { IWR.UnitDetailHandler_Coord		, "IWillRotate", "Unit coords changed"			})
table.insert(Event.Unit.Detail.Energy					, { IWR.UnitDetailHandler_Energy	, "IWillRotate", "Unit energy changed"			})
table.insert(Event.Unit.Detail.Health					, { IWR.UnitDetailHandler_Health	, "IWillRotate", "Unit health changed"			})
table.insert(Event.Unit.Detail.Mana						, { IWR.UnitDetailHandler_Mana		, "IWillRotate", "Unit mana changed"			})
table.insert(Event.Unit.Detail.Radius					, { IWR.UnitDetailHandler_Radius	, "IWillRotate", "Unit radius changed"			})
table.insert(Event.Buff.Add								, { IWR.BuffHandler_Add				, "IWillRotate", "New buff on unit"				})
table.insert(Event.Buff.Remove							, { IWR.BuffHandler_Remove			, "IWillRotate", "Buff removed from unit" 		})
table.insert(Event.Buff.Change							, { IWR.BuffHandler_Change			, "IWillRotate", "Buff changed on unit"			})
table.insert(Event.Ability.New.Add						, { IWR.AbilityHandler_Add			, "IWillRotate", "Player got new ability"		})
table.insert(Event.Ability.New.Remove					, { IWR.AbilityHandler_Remove		, "IWillRotate", "Player lost ability"			})
table.insert(Event.Ability.New.Usable.False				, { IWR.AbilityHandler_UsableF		, "IWillRotate", "Player ability unusable"		})
table.insert(Event.Ability.New.Usable.True				, { IWR.AbilityHandler_UsableT		, "IWillRotate", "Player ability usable"		})
table.insert(Event.Ability.New.Cooldown.Begin			, { IWR.AbilityHandler_CooldownB	, "IWillRotate", "Ability goes on cooldown"		})
table.insert(Event.Ability.New.Cooldown.End				, { IWR.AbilityHandler_CooldownE	, "IWillRotate", "Ability ends cooldown"		})
table.insert(Event.Ability.New.Range.False				, { IWR.AbilityHandler_RangeF		, "IWillRotate", "Player ability out of range"	})
table.insert(Event.Ability.New.Range.True				, { IWR.AbilityHandler_RangeT		, "IWillRotate", "Player ability in range"		})
table.insert(Event.Unit.Castbar							, { IWR.CastbarHandler				, "IWillRotate", "Castbar data have changed"	})
table.insert(Event.Unit.Detail.Level					, { IWR.UnitDetailHandler_Level		, "IWillRotate", "Player level changed"			})

for unit, unitdetails in pairs(IWR.UnitDetails) do
	table.insert(Library.LibUnitChange.Register(unit)	, { function(unitid) IWR.UnitHandler_Change(unit,unitid) end	, "IWillRotate", "Unit changed"	})
end

Command.Event.Attach(Event.Unit.Availability.Full, IWR.UnitAvailabilityFull, "Unit data available")
-----------
--/EVENTS--
-----------